package com.globalwave.filemanage.service;

import java.util.List;
import java.util.Random;
import java.util.Set;

import org.apache.commons.io.FileUtils;

import com.globalwave.base.BaseServiceImpl;
import com.globalwave.common.ArrayOrderList;
import com.globalwave.common.ArrayPageList;
import com.globalwave.common.C;
import com.globalwave.common.U;
import com.globalwave.common.Validator.AccountValidator;
import com.globalwave.common.entity.File;
import com.globalwave.common.entity.FileCriterion;
import com.globalwave.filemanage.FMCodeHelper;
import com.globalwave.filemanage.entity.Document;
import com.globalwave.filemanage.entity.DocumentCriterion;
import com.globalwave.filemanage.entity.SearchCriterion;
import com.globalwave.filemanage.searchengine.FulltextSearchOptions;
import com.globalwave.filemanage.searchengine.Hit;
import com.globalwave.filemanage.searchengine.Indexer;
import com.globalwave.filemanage.searchengine.Search;
import com.globalwave.filemanage.searchengine.SearchOptions;
import com.globalwave.filemanage.thumbnail.ThumbnailManager;

public class DocumentServiceImpl 
       extends BaseServiceImpl 
       implements DocumentService {
	
	private static Random randomSeed = new Random(System.currentTimeMillis()) ;

    public Document create(Document document) throws Exception {
    	
    	document.setSize_(new Long(document.getContent_().length())) ;
    	document.setTitle_(document.getName_()) ;
    	document.setCreated_on(U.currentTimestamp()) ;
    	
    	String type = document.getType_() ;    	
    	if (type.startsWith(".")) {
    		type = type.substring(1) ;
    	}
    	document.setType_(type.toLowerCase()) ;
    	
    	setDocumentId(document) ;
    	
    	final Document result = (Document) jdbcDao.insert(document, true);
    	
    	String path = document.getFolderPath() ;
    	
    	final java.io.File folder = new java.io.File(path) ;
    	
    	if (!folder.exists()) {
    		FileUtils.forceMkdir(folder) ;
    		FileUtils.forceMkdir(new java.io.File(path + "/thumbs/")) ;
    	}
    	
    	//path += "/" + document.getName_() + "." + document.getType_() ;
    	path += "/" + document.getDocument_id() ;
    	
    	if (logger.isDebugEnabled()) {
    		logger.debug("upload path:" + path) ;
    	}
    	java.io.File file = new java.io.File(path) ;
    	FileUtils.copyFile(document.getContent_(), file) ;
    	
    	ThumbnailManager thumbManaher = new ThumbnailManager();
    	thumbManaher.createTumbnail(document) ;
    	
    	Indexer indexer = new Indexer() ;
    	
    	try {
    	    indexer.addFile(file, document) ;
    	} catch (final Exception e) {
    		logger.error("add file to index fail, path[" + path + "]", e) ;
    	}
    	return result ;
    }
      
    /**
     * 
     * 18~20:保留
     * 6~17：序列号
     * 3~5:随机数
     * 2:校验
     * 1：权限，默认0
     * 
     * @param document
     * @throws Exception
     */
    private void setDocumentId(final Document document) throws Exception {
    	Long id = -1L ;

		AccountValidator validator = new AccountValidator() ;
    	int validbit = -1 ;
    	
    	for (int i = 0; i < 10 ; i ++) {
    		id = jdbcDao.getNextValue("FM_DOCUMENT_SEQ") ;
    		validbit = validator.getDocumentIdValidateBit(id);
    		if (validbit != -1) {
    			break ;
    		}
    	}
    	
    	if (validbit == -1) {
    		throw new Exception("document id generate Error!") ;
    	}
    	
		id = id * 100000 + (randomSeed.nextInt() % 1000) * 100 + validbit * 10 ;
    	document.setDocument_id(id) ;
    }

    public void update(Document file) throws Exception {
        jdbcDao.update(file) ;
    }

    public void delete(Document file) throws Exception {
        
        jdbcDao.delete(file) ;
        
    }

    public void deleteAll(Long[] fileIds) throws Exception {
        FileCriterion criterion = new FileCriterion() ;
        criterion.setFileIds(fileIds) ;
        jdbcDao.delete(File.class, criterion) ;
        
    }

    public ArrayPageList<Document> query(
    		DocumentCriterion fileCriterion, 
            int pageIndex, 
            int pageSize, 
            ArrayOrderList orderList) throws Exception {
        
        if (orderList == null) {
            orderList = new ArrayOrderList() ;
            orderList.addAsc("file_id") ;
        }
        
        return (ArrayPageList<Document>)jdbcDao.query(fileCriterion, pageIndex, pageSize, orderList, Document.class);
    }

	@Override
	public List<Long> findDeletedDocIds() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Set<Long> findDocIdByUserIdAndTag(Long userId, String tag)
			throws Exception {
		// TODO Auto-generated method stub
		return null;
	}

    public ArrayPageList<Document> search(
    		SearchCriterion criterion, 
            int pageIndex, 
            int pageSize) throws Exception {

		SearchOptions searchOptions = toSearchOptions(criterion);

		// Retrieve the search machinery
		Search search = Search.get(searchOptions);

		search.search();

		List<Hit> hits = search.getHits();

		//result.setTime(search.getExecTime());
		//result.setHasMore(search.isMoreHitsPresent());
		
		ArrayPageList<Document> result = new ArrayPageList<Document>(hits.size()) ;

		for (Hit hit : hits) {
			/*
			if (hit.getCustomId() == null) {
				// This document is a shortcut
				DocumentDAO docDAO = (DocumentDAO) Context.getInstance().getBean(DocumentDAO.class);
				// This settings are necessary for the 'open in folder'
				// feature.
				Document shortcutDoc = docDAO.findById(hit.getDocId());
				h.setId(shortcutDoc.getDocRef());
				h.setFolderId(shortcutDoc.getFolder().getId());
			} else {
				h.setId(hit.getDocId());
				h.setFolderId(hit.getFolderId());
			}*/
			final Document h = new Document() ;
			//h.setDate(hit.getDate());
			h.setCreated_on(hit.getCreation());
			h.setTitle_(hit.getTitle());
			//h.setCustomId(hit.getCustomId());
			h.setType_(hit.getType());
			h.setSummary_(hit.getSummary());
			h.setSize_(hit.getSize());
			//h.setScore(hit.getScore());
			
			// Check if the document is not an alias to visualize the
			// correct icon: if the document is an alias the FULL-TEXT
			// search returns a custom id null, the PARAMETRIC and TAG
			// searches return a doc ref equals to 0 or null
			/*
			if ((hit.getDocRef() == null || hit.getDocRef() == 0) && hit.getCustomId() != null)
				h.setIcon(FilenameUtils.getBaseName(hit.getIcon()));
			else
				h.setIcon("alias");
			guiResults.add(h);
			*/
			result.add(h) ;
		}
		//result.setHits(guiResults.toArray(new GUIHit[guiResults.size()]));

		return result;
    }

    protected SearchOptions toSearchOptions(SearchCriterion criterion) {
		SearchOptions searchOptions = Search.newOptions(criterion.getSearchType());
		//searchOptions.setTopOperator(criterion.getTopOperator());
		searchOptions.setDescription(criterion.getDescription());
		searchOptions.setExpression(criterion.getExpression_());
		//searchOptions.setMaxHits(criterion.getMaxHits());
		searchOptions.setName(criterion.getName_());
		//searchOptions.setUserId(criterion.getUserId());

		if (criterion.getSearchType() == SearchOptions.TYPE_FULLTEXT) {
			FulltextSearchOptions fulltextOptions = ((FulltextSearchOptions) searchOptions) ;
			//fulltextOptions.setTemplate(criterion.getTemplate());
			//fulltextOptions.setDateFrom(criterion.getDateFrom());
			//fulltextOptions.setDateTo(criterion.getDateTo());
			//fulltextOptions.setSourceDateFrom(criterion.getSourceDateFrom());
			//fulltextOptions.setSourceDateTo(criterion.getSourceDateTo());
			fulltextOptions.setCreationFrom(criterion.getCreated_from());
			fulltextOptions.setCreationTo(criterion.getCreated_to());
			//fulltextOptions.setExpressionLanguage(criterion.getExpressionLanguage());
			fulltextOptions.setExpressionLanguage(C.LOCALE_DEFAULT);
			//fulltextOptions.setFields(criterion.getFields());
			fulltextOptions.setFolderId(criterion.getFolder_id());
			//fulltextOptions.setFormat(criterion.getFormat());
			//fulltextOptions.setLanguage(criterion.getLanguage());
			fulltextOptions.setLanguage(C.LOCALE_DEFAULT);
			//fulltextOptions.setSearchInSubPath(criterion.isSearchInSubPath());
			//fulltextOptions.setSizeMax(criterion.getSizeMax());
			//fulltextOptions.setSizeMin(criterion.getSizeMin());
		}

		return searchOptions;
	}
    /*
    public java.io.File get(Long id) throws Exception {
        FileCriterion criterion = new FileCriterion() ;
        criterion.setFileId(id) ;
        
        ArrayPageList result = jdbcDao.query(FileCriterion.SQL_GET_FILE_ONLY, File.class, criterion, null, null, null, true);
        if (result.size() > 0 ) {
            return ((File) result.get(0)).getContent_() ;            
        } else {
            return null ;
        }
    }*/

	@Override
	public ArrayPageList<Document> listPhoto(
			DocumentCriterion fileCriterion,
			int pageIndex, 
			int pageSize, 
			ArrayOrderList orderList)
	throws Exception {
        
        if (fileCriterion == null) {
        	fileCriterion = new DocumentCriterion() ;
        }
        fileCriterion.setTypes(FMCodeHelper.getPhotoTypes()) ;

		return this.query(fileCriterion, pageIndex, pageSize, orderList);
	}
    
}
